package org.fusionide.builder;

import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.fusionide.builder.parsers.IParser;
import org.fusionide.builder.parsers.IParserHandler;
import org.fusionide.builder.parsers.ParserException;
import org.fusionide.builder.parsers.cfml.CFMLParser;



public class CFBuilder extends IncrementalProjectBuilder {

	class SampleDeltaVisitor implements IResourceDeltaVisitor {
		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
		 */
		public boolean visit(IResourceDelta delta) throws CoreException {
			IResource resource = delta.getResource();
			switch (delta.getKind()) {
			case IResourceDelta.ADDED:
				// handle added resource
				checkCF(resource);
				break;
			case IResourceDelta.REMOVED:
				// handle removed resource
				break;
			case IResourceDelta.CHANGED:
				// handle changed resource
				checkCF(resource);
				break;
			}
			// return true to continue visiting children.
			return true;
		}
	}

	class SampleResourceVisitor implements IResourceVisitor {
		public boolean visit(IResource resource) {
			checkCF(resource);
			// return true to continue visiting children.
			return true;
		}
	}

	class CFMLParserHandler extends IParserHandler {

		public CFMLParserHandler(IFile file) {
			super(file);
		}

		public void addMarker(ParserException e) {
			CFBuilder.this.addMarker(getFile(), e.getMessage(), e
					.getLineNumber(), e.getSeverity());
		}
	}

	public static final String BUILDER_ID = "FusionIDE.cfBuilder";

	private static final String MARKER_TYPE = "FusionIDE.xmlProblem";

	private void addMarker(IFile file, String message, int lineNumber,
			int severity) {

		try {
			IMarker marker = file.createMarker(MARKER_TYPE);
			marker.setAttribute(IMarker.MESSAGE, message);
			marker.setAttribute(IMarker.SEVERITY, severity);
			if (lineNumber == -1) {
				lineNumber = 1;
			}
			marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
		} catch (CoreException e) {
		}
	} 
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.core.internal.events.InternalBuilder#build(int,
	 *      java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
	 */

	protected IProject[] build(int kind, Map args, IProgressMonitor monitor)
			throws CoreException {
		if (kind == FULL_BUILD) {
			fullBuild(monitor);
		} else {
			IResourceDelta delta = getDelta(getProject());
			if (delta == null) {
				fullBuild(monitor);
			} else {
				incrementalBuild(delta, monitor);
			}
		}
		return null;
	}

	void checkCF(IResource resource) {
		if (resource instanceof IFile) {
			IFile file = (IFile) resource;
			deleteMarkers(file);

			if (file.getFileExtension().equalsIgnoreCase("cfm")
					|| file.getFileExtension().equalsIgnoreCase("cfc")) {
				IParserHandler reporter = new CFMLParserHandler(file);
				try {
					getParser("CFML").build(file, reporter);
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			}
		}
	}

	private void deleteMarkers(IFile file) {
		try {
			file.deleteMarkers(MARKER_TYPE, false, IResource.DEPTH_ZERO);
		} catch (CoreException ce) {
		}
	}

	protected void fullBuild(final IProgressMonitor monitor)
			throws CoreException {
		try {
			getProject().accept(new SampleResourceVisitor());
		} catch (CoreException e) {
		}
	}

	private IParser getParser(String fileType) {
		if (fileType.equalsIgnoreCase("CFML")) {
			return new CFMLParser();
		}
		return null;
	}

	protected void incrementalBuild(IResourceDelta delta,
			IProgressMonitor monitor) throws CoreException {
		// the visitor does the work.
		delta.accept(new SampleDeltaVisitor());
	}
}
